home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Modules / BackSpaceModules / Source / SpaceColorView / SpaceColorViewPart.m < prev    next >
Text File  |  1991-11-07  |  7KB  |  320 lines

  1. #import "SpaceColorViewPart.h"
  2. #import "Thinker.h"
  3. #import "psfuncts.h"
  4. #import <dpsclient/wraps.h>
  5. #import <appkit/NXImage.h>
  6. #import <zone.h>
  7. #import <mach.h>
  8. #import <c.h>
  9. #import <libc.h>
  10. #import <math.h>
  11.  
  12. #define PI (3.141592653589)
  13.  
  14. @implementation SpaceColorView
  15.  
  16. + initialize
  17. {
  18.     if ( self == [SpaceColorView class] )
  19.     {
  20.         // load PostScript procedures SpaceView needs
  21.         // must be careful these are loaded into the correct context
  22.         loadPSProcedures();
  23.     }
  24.     return self;
  25. }
  26.  
  27. //takes theta and distance and stuffs it into x &y for *p
  28. - convertToXY:(STAR *)p
  29. {
  30.     p->draw->x = floor(bounds.size.width / 2 + (p->distance * cos(p-> theta)));
  31.     p->draw->y = floor(bounds.size.height / 2 + (p->distance * sin(p-> theta)));
  32.     return self;
  33. }
  34.  
  35.  
  36. - oneStep
  37. {
  38.     int i, count, starsInArray = 0;
  39.     STAR *p;
  40.     NXPoint *t;
  41.     
  42.     if (nstars < NSTARS) [self addStar];
  43.  
  44.     for (i=0; i<nstars; i++)
  45.     {
  46.         p = &stars[i];
  47.         p->distance += p->delta;
  48.         p->delta *= p->ddelta;
  49.  
  50.         [self convertToXY:p];
  51.  
  52.         // only draw the star if it moved > 1 pixel
  53.         if (p->draw->x != p->erase->x || 
  54.             p->draw->y != p->erase->y)
  55.         {
  56.             BOOL mustErase = NO;
  57.             // add star to the erasure array
  58.             b[starsInArray] = *p->erase;
  59.             bc[starsInArray] = p->c;
  60.  
  61.             if (p->distance > p->changepoint[p->changemode])
  62.             {
  63.                 (p->c)++;    // increment character for next star size
  64.                 (p->changemode)++;
  65.             }
  66.  
  67.             // clipping is off, so we must not draw outside view.
  68.             // replace stars that go too far...
  69.             if (p->draw->x < 0 ||
  70.                 p->draw->y < 0 ||
  71.                 p->draw->x + 7 > bounds.size.width ||
  72.                 p->draw->y + 7 > bounds.size.height)
  73.             {
  74.                 [self replaceStarAt:i];
  75.                 mustErase = YES;
  76.             }
  77.  
  78.             w[starsInArray] = *p->draw;
  79.             wc[starsInArray] = p->c;
  80.             wColor[starsInArray] = starColor[i];
  81.             
  82.             if (mustErase || [self allowStars:p]) starsInArray++;
  83.         
  84.             t = p->draw; p->draw = p->erase; p->erase = t;
  85.         }
  86.     }
  87.  
  88.     bc[starsInArray] = wc[starsInArray] = 0;    //null terminate string
  89.     if (starsInArray)
  90.     {
  91.         for (i=0; i<(starsInArray-1); i++)
  92.         {
  93.             bOffsets[i].x = b[i+1].x - b[i].x;
  94.             bOffsets[i].y = b[i+1].y - b[i].y;
  95.             wOffsets[i].x = w[i+1].x - w[i].x;
  96.             wOffsets[i].y = w[i+1].y - w[i].y;
  97.         }
  98.         bOffsets[i].x = bOffsets[i].y = wOffsets[i].x = wOffsets[i].y = 0;
  99.  
  100.         count = 0;
  101.         while (count < starsInArray)
  102.         {    char tc;
  103.             int j;
  104.             // You get the best performance if you put out all the stars
  105.             // at once.  This causes noticable flicker, so I put out 
  106.             // 100 of the stars per iteration.  This gives reasonable speed
  107.             // and flicker is hardly noticable.  Besides, stars
  108.             // _should_ flicker a little...
  109.         
  110.             int t = (starsInArray - count);
  111.             i = (t < STARSPERIT)?t:STARSPERIT;
  112.             j = i + count;
  113.             
  114.             PSsetgray(NX_BLACK);
  115.             tc = bc[j]; bc[j] = 0;
  116.             PSWXYShow(b[count].x, b[count].y, &bc[count], 
  117.                 (float *)(&bOffsets[count].x), i*2);
  118.             bc[j] = tc;
  119.             
  120.             NXSetColor(wColor[count]); //PSsetgray(NX_WHITE);
  121.             tc = wc[j]; wc[j] = 0;
  122.             PSWXYShow(w[count].x, w[count].y, &wc[count], 
  123.                 (float *)(&wOffsets[count].x), i*2);
  124.             wc[j] = tc;
  125.             
  126.             count += STARSPERIT;
  127.         }
  128.     }
  129.  
  130.     return self;
  131. }
  132.  
  133. // returns yes if the star is outside the avoidance rectangle
  134. // this is really fast and loose but it works acceptibly well
  135. // ps I could just use NXIntersectsRect() but I want to avoid
  136. // trap overhead.  Call me paranoid...
  137. - (BOOL) allowStars:(const STAR *)p
  138. {
  139.     // just return if voidRect not set
  140.     if ((!voidRect.size.width) ||
  141.         p->draw->x < voidRect.origin.x ||
  142.         p->draw->y < voidRect.origin.y ||
  143.         p->draw->x+7 > voidRect.origin.x+voidRect.size.width ||
  144.         p->draw->y+7 > voidRect.origin.y+voidRect.size.height ||
  145.  
  146.         p->erase->x < voidRect.origin. x ||
  147.         p->erase->y < voidRect.origin. y ||
  148.         p->erase->x+7 > voidRect.origin.x+voidRect.size.width ||
  149.         p->erase->y+7 > voidRect.origin.y+voidRect.size.height) return YES;
  150.  
  151.     return NO;
  152. }
  153.  
  154. - initFrame:(NXRect *)frameRect
  155. {
  156.     [super initFrame:frameRect];
  157.     [self allocateGState];        // For faster lock/unlockFocus
  158.     [self setClipping:NO];        // even faster...
  159.     [self setRadius];
  160.     loadPSProcedures();
  161.     PSWDefineFont("StarFont");
  162.     PSselectfont("StarFont", 1.0);
  163.  
  164.     return self;
  165. }
  166.  
  167. - drawSelf:(const NXRect *)rects :(int)rectCount
  168. {
  169.     NXRect t = {0,0,1,1};
  170.  
  171.     if (!rects || !rectCount) return self;
  172.     
  173.     PSsetrgbcolor(.333,.222,.111);
  174.     NXRectFill(&t);    //yucky trick for window depth promotion!
  175.  
  176.     PSselectfont("StarFont", 1.0);
  177.  
  178.     PSsetgray(NX_BLACK);
  179.     //NXRectFill(rects);
  180.  
  181.     return self;
  182. }
  183.  
  184. - sizeTo:(NXCoord)width :(NXCoord)height
  185. {
  186.     [super sizeTo:width :height];
  187.  
  188.     if (oldSize.width != bounds.size.width ||
  189.             oldSize.height != bounds.size.height)
  190.     {
  191.         oldSize.width = bounds.size.width;
  192.         oldSize.height = bounds.size.height;
  193.         [self setRadius];
  194.         nstars = 0;
  195.         [self display];
  196.     }
  197.     
  198.     return self;
  199. }
  200.  
  201. // only call addStar if there is room in the starts array!
  202. - addStar
  203. {
  204.     [self replaceStarAt:nstars++];
  205.     return self;
  206. }
  207.  
  208. - replaceStarAt:(int)index
  209. {
  210.     float dist, t;
  211.     STAR *p = &stars[index];
  212.  
  213. top:
  214.     p->theta = randBetween(0,(2*PI));
  215.     
  216.     p->distance = randBetween(1, radius);
  217.     
  218.     p->delta = (0.2);
  219.  
  220.     p->ddelta = randBetween(1.0, 1.1);
  221.  
  222.     starColor[index] = NXConvertHSBToColor(randBetween(0.0, 1.0),
  223.         0.5 + randBetween(0.0, 0.5), 1.0);
  224.  
  225.  
  226.     t = randBetween(0, (0.42*radius));
  227.     dist = MAX(20,t);
  228.     p->changepoint[0] = p->distance + 5;            // to b
  229.     p->changepoint[1] = p->changepoint[0] - 5 + dist + dist;    // to c
  230.  
  231.  
  232.     p->changepoint[2] = p->changepoint[1] + dist;    // to d
  233.     p->changepoint[3] = p->changepoint[2] + dist;    // to e
  234.     p->changepoint[4] = p->changepoint[3] + dist;    // to f
  235.     p->changepoint[5] = 100000;                        // never change to g
  236.  
  237.     p->changemode = 0;
  238.     
  239.     if ((++toggle) & 1) p->c = 'a';
  240.     else p->c = 'g';
  241.  
  242.     p->draw = &p->r1;
  243.     p->erase = &p->r2;
  244.     [self convertToXY:p];
  245.     if (p->draw->x < 0 ||
  246.         p->draw->y < 0 ||
  247.         p->draw->x + 7 > bounds.size.width ||
  248.         p->draw->y + 7 > bounds.size.height)
  249.     {
  250.         // just to be safe. Remember, no clipping is done.
  251.         goto top;
  252.     }
  253.  
  254.     p->r2 = p->r1;
  255.  
  256.     return self;
  257. }
  258.  
  259. - setRadius
  260. {
  261.     int val = MIN(bounds.size.width, bounds.size.height);
  262.     radius = val / 2;
  263.     return self;
  264. }
  265.  
  266. - (const char *)windowTitle
  267. {
  268.     return "The Final Frontier";
  269. }
  270.  
  271. - setVoidRect:(const NXRect *)r
  272. {
  273.     voidRect = *r;
  274.     return self;
  275. }
  276.  
  277. - didLockFocus
  278. {
  279.     PSselectfont("StarFont", 1.0);
  280.     return self;
  281. }
  282.  
  283. - (BOOL)useBufferedWindow
  284. {    return NO;
  285. }
  286.  
  287. @end
  288.  
  289. @implementation View(nonretainedFillMethod)
  290.  
  291. // I add this method as a category of View to be sure that all
  292. // my views implement it.  I really want to use nonretained windows
  293. // but they are drawn via drawSelf at all kinds of goofy times.  It
  294. // seems like the kit kind of throws up its hands when it doesn't have
  295. // a buffer to draw from, so you get a lot more drawSelfs than you need,
  296. // and sometimes you don't get them when you really want them.  I know
  297. // when I need the background filled in black, so I factor that out of
  298. // my drawSelf and then drawself only draws things that are already on
  299. // screen so you don't see it happen.  I will only call this method on
  300. // a nonretained (and full screen) window.
  301.  
  302. - fillBoundsWithBlack
  303. {
  304.     [self lockFocus];
  305.     PSsetgray(NX_BLACK);
  306.     NXRectFill(&bounds);
  307.     [self unlockFocus];
  308.     return self;
  309. }
  310.  
  311. @end
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.